using System;
using System.Collections.Generic;
using System.Text;
using Calc.Operations;
using NUnit.Framework;

namespace Calc.TestHelpers
{
	public static class EquationComparer
	{
		public static bool Compare(EquationNode node, IOperand oper)
		{
			BinaryOperator bop = null;
			switch ( node.Type )
			{
				case EquationNodeType.AddOp:
					Assert.AreEqual(typeof(AddOperator), oper.GetType());

					bop = (BinaryOperator)oper;
					Compare(node.Left, bop.LeftSide);
					Compare(node.Right, bop.RightSide);
					break;
				case EquationNodeType.SubtractOp:
					Assert.AreEqual(typeof(SubtractOperator), oper.GetType());

					bop = (BinaryOperator)oper;
					Compare(node.Left, bop.LeftSide);
					Compare(node.Right, bop.RightSide);
					break;
				case EquationNodeType.MultiplyOp:
					Assert.AreEqual(typeof(MultiplyOperator), oper.GetType());

					bop = (BinaryOperator)oper;
					Compare(node.Left, bop.LeftSide);
					Compare(node.Right, bop.RightSide);
					break;
				case EquationNodeType.DivideOp:
					Assert.AreEqual(typeof(DivideOperator), oper.GetType());

					bop = (BinaryOperator)oper;
					Compare(node.Left, bop.LeftSide);
					Compare(node.Right, bop.RightSide);
					break;
				case EquationNodeType.ModuloOp:
					Assert.AreEqual(typeof(ModuloOperator), oper.GetType());

					bop = (BinaryOperator)oper;
					Compare(node.Left, bop.LeftSide);
					Compare(node.Right, bop.RightSide);
					break;
				case EquationNodeType.Function:
					Assert.AreEqual(typeof(Function), oper.GetType());

					Function func = (Function)oper;
					Assert.AreEqual(node.Name, func.Name);
					Assert.AreEqual(node.Parameters.Count, func.Variables.Count,
									"Parameter count for function node does not match function variable count");

					for ( int i = 0; i < node.Parameters.Count; i++ )
					{
						Compare(node.Parameters[i], func.Variables[i]);
					}
					break;
				case EquationNodeType.Variable:
					Assert.AreEqual(typeof(Variable), oper.GetType());

					Variable var = (Variable)oper;

					Assert.AreEqual(node.Name, var.Name);
					break;
				case EquationNodeType.Constant:
					Assert.AreEqual(typeof(Constant), oper.GetType());

					Constant con = (Constant)oper;

					Assert.AreEqual(node.Value, con.Value, "Constant value does not match expected value.");
					break;
				case EquationNodeType.AssignmentOp:
					Assert.AreEqual(typeof(AssignmentOperator), oper.GetType());

					bop = (BinaryOperator)oper;
					Compare(node.Left, bop.LeftSide);
					Compare(node.Right, bop.RightSide);
					break;
				case EquationNodeType.Parenthesese:
					Assert.AreEqual(typeof(Parenthesese), oper.GetType());

					Parenthesese par = (Parenthesese) oper;

					Compare(node.Left, par.Operation);
					break;
			}

			return true;
		}
	}
}
